package com.app.system.utils;

import com.app.system.permission.model.UserInfo;
import com.app.system.permission.service.UserInfoService;
import com.app.system.utils.exception.Precondition;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.beans.propertyeditors.CustomNumberEditor;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.context.ApplicationContext;
import org.springframework.util.ResourceUtils;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.context.support.WebApplicationContextUtils;

import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.UnknownHostException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 网络操作工具类
 */
@SuppressWarnings("all")
public class WebUtils {

    private static UserInfoService userInfoService;

    /**
     * 获取项目根目录
     *
     * @return
     */
    public static String getRootPath() {
        try {
            return ResourceUtils.getURL("classpath:").getPath();
        } catch (FileNotFoundException e) {
        }
        return "";
    }

    /**
     * 获取当前登录用户名
     *
     * @return
     */
    public static String getLoginUserName() {
        return (String) SecurityUtils.getSubject().getPrincipal();
    }

    /**
     * 获取当前登录用户信息
     *
     * @return
     */
    @CacheEvict(value = {"userInfoCache", "sysRoleCache", "sysPermissionCache"}, allEntries = true)
    public static UserInfo getLoginUserInfo() {
        ApplicationContext applicationContext = ApplicationContextProvider.getApplicationContext();
        userInfoService = (UserInfoService) applicationContext.getBean(UserInfoService.class);
        return userInfoService.findByUsername(getLoginUserName());
    }

    public static WebApplicationContext getWebApplicationContext() {
        HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
        return getWebApplicationContext(request);
    }

    public static WebApplicationContext getWebApplicationContext(HttpServletRequest request) {
        WebApplicationContext webAppCtx = WebApplicationContextUtils.getRequiredWebApplicationContext(request.getSession().getServletContext());
        return webAppCtx;
    }

    public static void bind(ServletRequest request, Object command) {
        ServletRequestDataBinder binder = new ServletRequestDataBinder(command);
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
        binder.registerCustomEditor(Integer.class, new CustomNumberEditor(Integer.class, true));
        binder.registerCustomEditor(Double.class, new CustomNumberEditor(Double.class, true));
        binder.registerCustomEditor(Long.class, (String) null, new CustomNumberEditor(Long.class, true));
        binder.registerCustomEditor(Float.class, (String) null, new CustomNumberEditor(Float.class, true));
        binder.registerCustomEditor(BigDecimal.class, (String) null, new CustomNumberEditor(BigDecimal.class, true));
        binder.registerCustomEditor(Byte.class, (String) null, new CustomNumberEditor(Byte.class, true));
        binder.bind(request);
        BindingResult bindingResult = binder.getBindingResult();
        List list = bindingResult.getAllErrors();
        Iterator i$ = list.iterator();

        while (i$.hasNext()) {
            Object error = i$.next();
        }

        Precondition.checkSqdsArguement(bindingResult.getErrorCount() <= 0, "您输入的数据有误。");
    }

    /**
     * 获取ServletRequestAttribute
     *
     * @return
     */
    private static ServletRequestAttributes getServletRequestAttributes() {
        return (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
    }

    /**
     * 获取系统访问地址（例如：http://xxx.bjjmdf.com 或  http://192.168.1.101:8080）
     *
     * @return
     */
    public static String getSystemAccess() {
        HttpServletRequest request = getRequest();
        StringBuffer url = new StringBuffer("");
        url.append(request.getScheme()).append("://");
        url.append(request.getServerName());
        int serverPort = request.getServerPort();
        if (serverPort > 0) {
            url.append(":").append(serverPort);
        }
        return url.toString();
    }

    /**
     * 保存到request域中
     *
     * @param key
     * @param value
     */
    public static void saveRequest(String key, Object value) {
        getServletRequestAttributes().setAttribute(key, value, ServletRequestAttributes.SCOPE_REQUEST);
    }

    /**
     * 重定向的方法
     *
     * @param url
     */
    public static void redirect(String url) {
        try {
            getResponse().sendRedirect(url);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 转发
     *
     * @param url
     */
    public static void forward(String url) {
        try {
            getRequest().getRequestDispatcher(url).forward(getRequest(), getResponse());
        } catch (ServletException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void saveMapToRequest(Map<String, Object> map) {
        if (map == null || map.size() == 0) {
            return;
        }
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();
            saveRequest(key, value);
        }
    }

    /**
     * 保存session域中
     *
     * @param key
     * @param value
     */
    public static void saveSession(String key, Object value) {
        getServletRequestAttributes().setAttribute(key, value, ServletRequestAttributes.SCOPE_SESSION);
    }

    /**
     * 从request中获取对象
     *
     * @param key
     * @return
     */
    public static Object getFromRequest(String key) {
        return getServletRequestAttributes().getAttribute(key, ServletRequestAttributes.SCOPE_REQUEST);
    }

    /**
     * 从session中获取对象
     *
     * @param key
     * @return
     */
    public static Object getFromSession(String key) {
        return getServletRequestAttributes().getAttribute(key, ServletRequestAttributes.SCOPE_SESSION);
    }

    /**
     * 获取request对象
     *
     * @return
     */
    public static HttpServletRequest getRequest() {
        return getServletRequestAttributes().getRequest();
    }

    /**
     * 获取session对象
     *
     * @return
     */
    public static HttpSession getSession() {
        return getRequest().getSession();
    }

    /**
     * 获取response
     *
     * @return
     */
    public static HttpServletResponse getResponse() {
        return getServletRequestAttributes().getResponse();
    }


    public static String getPostData() {
        String str = (String) getFromRequest("str_bean");
        if (str == null) {
            str = getLine();
            saveRequest("str_bean", str);
        }
        return str;
    }

    /**
     * 从ServletRquest中获取字符串
     *
     * @return
     */
    private static String getLine() {
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new InputStreamReader(getRequest().getInputStream(), "utf-8"));
            String line = null;
            StringBuffer sb = new StringBuffer();
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
            return sb.toString();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                reader.close();
            } catch (IOException e) {
                reader = null;
                e.printStackTrace();
            }
        }
        return null;
    }

//    public static boolean ping(String ipAddress){
//        return ping(ipAddress,5,5000);
//    }


//    public static boolean ping(String ipAddress, int pingTimes, int timeOut) {
//        BufferedReader in = null;
//        String pingCommand = null;
//        Runtime r = Runtime.getRuntime();
//        String osName = System.getProperty("os.name");
//        if(osName.contains("Windows")){
//            //将要执行的ping命令,此命令是windows格式的命令
//            pingCommand = "ping " + ipAddress + " -n " + pingTimes    + " -w " + timeOut;
//            try {
//                //执行命令并获取输出
//                Process p = r.exec(pingCommand);
//                if (p == null) {
//                    return false;
//                }
//                in = new BufferedReader(new InputStreamReader(p.getInputStream()));
//                int connectedCount = 0;
//                String line = null;
//                while ((line = in.readLine()) != null) {
//                    connectedCount += getCheckResult(line,osName);
//                }
//                //如果出现类似=23 ms ttl=64(TTL=64 Windows)这样的字样,出现的次数=测试次数则返回真
//                return connectedCount == pingTimes;
//                //return connectedCount >= 2 ? true : false;
//            } catch (Exception ex) {
//                ex.printStackTrace(); //出现异常则返回假
//                return false;
//            } finally {
//                try {
//                    in.close();
//                } catch (IOException e) {
//                    e.printStackTrace();
//                }
//            }
//        }else{
//            //将要执行的ping命令,此命令是Linux格式的命令
//            //-c:次数,-w:超时时间(单位/ms)  ping -c 10 -w 0.5 192.168.120.206
//            //pingCommand = "ping " + " -c " + "4" + " -w " + "2 " + ipAddress;
//            boolean ret = false;
//            try {
//                String [] command={"/bin/sh", "-c", "ping -c 4 " + ipAddress};
//                Process process = Runtime.getRuntime().exec(command);
//                ret = process.waitFor(timeOut, TimeUnit.SECONDS);
//                if(!ret){
//                    System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>运行超时了。。。。。");
//                } else {
//                    ret = process.exitValue() == 0;
//                }
//                process.destroy();
//            } catch (Exception e) {
//                e.printStackTrace();
//            }
//            return ret;
//        }
//
//
//    }
    //若line含有=18 ms ttl=64字样,说明已经ping通,返回1,否則返回0.
//    private static int getCheckResult(String line,String osName) {
//        if(osName.contains("Windows")){
//            Pattern pattern = Pattern.compile("(\\d+ms)(\\s+)(TTL=\\d+)",    Pattern.CASE_INSENSITIVE);
//            Matcher matcher = pattern.matcher(line);
//            while (matcher.find()) {
//                return 1;
//            }
//            return 0;
//        }else{
//            if(line.contains("ttl=")){
//                return 1;
//            }
//        }
//        return 0;
//    }


    public static boolean isWindowsOS() {
        boolean isWindowsOS = false;
        String osName = System.getProperty("os.name");
        if (osName.toLowerCase().indexOf("windows") > -1) {
            isWindowsOS = true;
        }
        return isWindowsOS;
    }

    /**
     * 获取本机ip地址（程序部署的服务器地址），并自动区分Windows还是linux操作系统
     *
     * @return String
     */
    public static String getLocalIP() {
        String sIP = "";
        InetAddress ip = null;
        try {
            //如果是Windows操作系统
            if (isWindowsOS()) {
                ip = InetAddress.getLocalHost();
            }
            //如果是Linux操作系统
            else {
                boolean bFindIP = false;
                Enumeration<NetworkInterface> netInterfaces = (Enumeration<NetworkInterface>) NetworkInterface.getNetworkInterfaces();
                while (netInterfaces.hasMoreElements()) {
                    if (bFindIP) {
                        break;
                    }
                    NetworkInterface ni = (NetworkInterface) netInterfaces.nextElement();
                    //----------特定情况，可以考虑用ni.getName判断
                    //遍历所有ip
                    Enumeration<InetAddress> ips = ni.getInetAddresses();
                    while (ips.hasMoreElements()) {
                        ip = (InetAddress) ips.nextElement();
                        if (ip.isSiteLocalAddress()
                                && !ip.isLoopbackAddress()   //127.开头的都是lookback地址
                                && ip.getHostAddress().indexOf(":") == -1) {
                            bFindIP = true;
                            break;
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (null != ip) {
            sIP = ip.getHostAddress();
        }
        return sIP;
    }

    /**
     * 得到当前用户ip
     *
     * @param request
     * @return
     */
    public static String getIpAddr(HttpServletRequest request) {
        String ipAddress = request.getHeader("x-forwarded-for");
        if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader("Proxy-Client-IP");
        }
        if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getRemoteAddr();
            if ("127.0.0.1".equals(ipAddress) || "0:0:0:0:0:0:0:1".equals(ipAddress)) {
                //根据网卡取本机配置的IP
                InetAddress inet = null;
                try {
                    inet = InetAddress.getLocalHost();
                } catch (UnknownHostException e) {
                }
                ipAddress = inet.getHostAddress();
            }
        }
        //对于通过多个代理的情况，第一个IP为客户端真实IP,多个IP按照','分割
        if (ipAddress != null && ipAddress.length() > 15) { //"***.***.***.***".length() = 15
            if (ipAddress.indexOf(",") > 0) {
                ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));
            }
        }
        return ipAddress;
    }
}